import pygame, sys, os
from mazesettings import *
from pygame.locals import *
from questionlist import *
import pygame.freetype
from mazelevel import Level
from mazedata import maze_level

# pygame setup
pygame.init()
screen = pygame.display.set_mode((screen_width,screen_height))
clock = pygame.time.Clock()

# title
pygame.display.set_caption('Level 8')

# font settings
font = pygame.font.SysFont('Constantia', 30)
font1 = pygame.freetype.SysFont('Constantia', 30) # for the wrap function
font2 = pygame.font.SysFont('Constantia', 40)
font_big = pygame.font.SysFont('Lucida Sans', 40)

# globel color
bg = (50, 50, 50)
con_col = (110, 255, 250)
cong_col = (255, 255, 120)
black = (0, 0, 0)
white = (255, 255, 255)

# end image
end_image = pygame.image.load('../graphics/end.png').convert_alpha()
# button animation settings
clicked = False
counter = 1
score = 0

# function for outputting text onto the screen
def draw_text(text,font,text_col,x,y):
    img = font.render(text, True, text_col) 
    screen.blit(img,(x,y))

class button():
    #colors for button and text
    button_col = (60, 195, 255)
    hover_col = (75, 225, 255)
    click_col = (50, 150, 255)
    text_col = (255, 255, 255)
    wrong_col = (215, 70, 70)
    ans_col = (50, 190, 120)
    width = 800
    height = 50
    qwidth = 800
    qheight = 200
    spacex = 230
    spacey = 120

    def __init__(self, x, y, text):
        self.x = x
        self.y = y
        self.text = text

    # split the long sentense and wrap
    def word_wrap(self, surf, text, font, color):
        font.origin = True
        words = text.split(' ')
        line_spacing = font.get_sized_height() + 2 # get the line height
        x, y = self.spacex, line_spacing + self.spacey # set the place of the questions
        space = font.get_rect(' ')
        for word in words: # adjust the long sentence's place and warning when the sentence length is out ou range
            bounds = font.get_rect(word)
            if x + bounds.width + bounds.x >= self.qwidth + self.spacex - 40:
                x, y = self.spacex, y + line_spacing
            if x + bounds.width + bounds.x >= self.qwidth + self.spacex - 40: # Error Warning
                raise ValueError("word too wide for the surface")
            if y + bounds.height - bounds.y >= self.qheight + self.spacey: # Error Warning
                raise ValueError("text to long for the surface")
            font.render_to(surf, (x, y), None, color)
            x += bounds.width + space.width
        return x, y
    
    def quest(self):
        # create pygame Rect object for the button (frame)
        button_rect = Rect(self.x, self.y, self.qwidth, self.qheight)
        pygame.draw.rect(screen, self.button_col, button_rect, 2, border_radius = 12)

        # add text to button
        self.word_wrap(screen, self.text, font1, self.text_col)
    
    def cong(self):
        # create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.qwidth, self.qheight)

        pygame.draw.rect(screen, (255,255,182), button_rect, 2, border_radius = 12)

        # add text to button
        text_img = font2.render(self.text, True, cong_col)
        text_len = text_img.get_rect(center = button_rect.center)
        screen.blit(text_img,text_len)

    def again(self):
        # create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.qwidth, self.qheight)

        pygame.draw.rect(screen, self.button_col, button_rect, 2, border_radius = 12)

        # add text to button
        text_img = font2.render(self.text, True, self.button_col)
        text_len = text_img.get_rect(center = button_rect.center)
        screen.blit(text_img,text_len)
    
    def none_answer(self):
        # create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.width, self.height)

        pygame.draw.rect(screen, self.button_col, button_rect, border_radius = 12)
        pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)

        # add text to button
        text_img = font.render(self.text, True, self.text_col)
        text_len = text_img.get_rect(center = button_rect.center)
        screen.blit(text_img,text_len)

    def show_answer(self):
        # create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.width, self.height)

        pygame.draw.rect(screen, self.ans_col, button_rect, border_radius = 12)
        pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)

        # add text to button
        text_img = font.render(self.text, True, self.text_col)
        text_len = text_img.get_rect(center = button_rect.center)
        screen.blit(text_img,text_len)

    def wrong_answer(self):
        # create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.width, self.height)

        # timing and delaying
        waiting = True
        waited_time = pygame.time.get_ticks()
        while waiting:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
            # draw the button
            pygame.draw.rect(screen, self.wrong_col, button_rect, border_radius = 12)
            pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)

            # add text to button
            text_img = font.render(self.text, True, self.text_col)
            text_len = text_img.get_rect(center = button_rect.center)
            screen.blit(text_img,text_len)
            pygame.display.update()
            clock.tick(15)
            if pygame.time.get_ticks() - waited_time > 2000:
                waiting = False
    
    def right_answer(self):
        #create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.width, self.height)

        # timing and delaying
        waiting = True
        waited_time = pygame.time.get_ticks()
        while waiting:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
            # draw the button
            pygame.draw.rect(screen, self.ans_col, button_rect, border_radius = 12)
            pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)
  
            #add text to button
            text_img = font.render(self.text, True, self.text_col)
            text_len = text_img.get_rect(center = button_rect.center)
            screen.blit(text_img,text_len)
            pygame.display.update()
            clock.tick(15)
            if pygame.time.get_ticks() - waited_time > 2000:
                waiting = False

    def draw_button(self):
        global clicked
        action = False

        # get mouse position
        pos = pygame.mouse.get_pos()

        # create pygame Rect object for the button
        button_rect = Rect(self.x, self.y, self.width, self.height)

        # check mouseover and clicked condition
        if button_rect.collidepoint(pos):
            # on click
            if pygame.mouse.get_pressed()[0] == 1:
                clicked = True
                pygame.draw.rect(screen, self.click_col, button_rect, border_radius = 12)
                pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)
            # after click, in case for multiple clicks, meanwhile animate the button
            elif pygame.mouse.get_pressed()[0] == 0 and clicked == True:
                clicked = False
                action = True
            # put the mouse point on the button without clicking
            else:
                pygame.draw.rect(screen, self.hover_col, button_rect, border_radius = 12)
                pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)
        # normal condition
        else:
            pygame.draw.rect(screen, self.button_col, button_rect, border_radius = 12)
            pygame.draw.rect(screen, white, button_rect, 2, border_radius = 12)

        # add text to button
        text_img = font.render(self.text, True, self.text_col)
        text_len = text_img.get_rect(center = button_rect.center)
        screen.blit(text_img,text_len)
        return action # animation

# draw the quiz screen
def questions_run():

    # background color
    screen.fill(bg)

    global counter # count the question number
    global score # count the score

    # draw the four buttons to be clicked on a certain position
    # using list and dictionary to aquire specific answer
    if counter <= 20:

        # draw button
        a = button(200, 350, ques[(counter-1)]['A']) # list[] begins from 0, counter begins from 1
        b = button(200, 450, ques[(counter-1)]['B'])
        c = button(200, 550, ques[(counter-1)]['C'])
        d = button(200, 650, ques[(counter-1)]['D'])
        q = button(200, 100, ques[(counter-1)]['Q'])

        # draw question
        q.quest()

        # judging clicking
        # comparing reply with the answer list
        # react with different animation
        if a.draw_button():
            if answer[counter-1] != 'B':
                b.none_answer()
            else:
                b.show_answer()
            if answer[counter-1] != 'C':
                c.none_answer()
            else:
                c.show_answer()
            if answer[counter-1] != 'D':
                d.none_answer()
            else:
                d.show_answer()
            if answer[counter-1] != 'A':
                a.wrong_answer()
            else:
                a.right_answer()
                score += 5
            counter += 1

        if b.draw_button():
            if answer[counter-1] != 'A':
                a.none_answer()
            else:
                a.show_answer()
            if answer[counter-1] != 'C':
                c.none_answer()
            else:
                c.show_answer()
            if answer[counter-1] != 'D':
                d.none_answer()
            else:
                d.show_answer()
            if answer[counter-1] != 'B':
                b.wrong_answer()
            else:
                b.right_answer()
                score += 5
            counter += 1

        if c.draw_button():
            if answer[counter-1] != 'A':
                a.none_answer()
            else:
                a.show_answer()
            if answer[counter-1] != 'B':
                b.none_answer()
            else:
                b.show_answer()
            if answer[counter-1] != 'D':
                d.none_answer()
            else:
                d.show_answer()
            if answer[counter-1] != 'C':
                c.wrong_answer()
            else:
                c.right_answer()
                score += 5  
            counter += 1

        if d.draw_button():
            if answer[counter-1] != 'A':
                a.none_answer()
            else:
                a.show_answer()
            if answer[counter-1] != 'B':
                b.none_answer()
            else:
                b.show_answer()
            if answer[counter-1] != 'C':
                c.none_answer()
            else:
                c.show_answer()
            if answer[counter-1] != 'D':
                d.wrong_answer()
            else:
                d.right_answer()
                score += 5
            counter += 1
        
        # draw the counter on the screen
        counter_img = font.render(str(counter) + '/20', True, con_col)
        screen.blit(counter_img, (20,20))

    # jump out of loop
    # judging the score and give different result
    else:
        # high score
        if score >= 65:
            # presenting the congratulation information
            q = button(200, 200, 'Congratulation!')
            q.cong()
            # presenting the score
            score_img = font2.render('Score: '+ str(score), True, con_col)
            screen.blit(score_img, (520,500))
            # exit
            draw_text('PRESS SPACE TO EXIT',font_big,'white',390,400)
            # play again
            draw_text('PRESS ENTER TO PLAY AGAIN',font_big,'white',320,450)
            key = pygame.key.get_pressed()
            if key[pygame.K_SPACE]:
                pygame.quit()
                sys.exit()
            elif key[pygame.K_RETURN]:
                screen.blit(end_image,(0,0,screen_width,screen_height))

        # low score
        else:
            q = button(200, 200, 'Try Again!')
            q.again()
            score_img = font2.render('Score: '+ str(score), True, con_col)
            screen.blit(score_img, (520,500))
            # exit
            draw_text('PRESS SPACE TO EXIT',font_big,'white',390,400)
            # play again
            draw_text('PRESS ENTER TO PLAY AGAIN',font_big,'white',320,450)
            key = pygame.key.get_pressed()
            if key[pygame.K_SPACE]:
                pygame.quit()
                sys.exit()
            elif key[pygame.K_RETURN]:
                pygame.quit()
                os.system('python main.py')
                quit()
class Game:

    # get different status
    def __init__(self):
        self.level = Level(maze_level, screen, self.create_q)
        self.status = 'mazelevel' # initialize with the maze screen

    def create_level(self):
        self.level = Level(maze_level, screen, self.create_q)
        self.status = 'mazelevel'

    def create_q(self, screen):
        '''self.questions = mazeq1(screen)'''
        self.status = 'mazeq1' # changing to the quiz screen

    def run(self):
        if self.status == 'mazelevel':
            self.level.run()
        elif self.status == 'mazeq1':
            questions_run()

game = Game()

# main loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    
    screen.fill('black')
    game.run()

    pygame.display.update()
    clock.tick(60)